<template>
    <div class="excel-uploader" :style="{ display: inline ? 'inline-flex' : 'flex', gap: '8px', alignItems: 'center' }">
      <el-upload
        ref="uploader"
        :auto-upload="!manual"                
        :limit="limit"
        :accept="accept"
        :show-file-list="showFileList"
        :on-exceed="handleExceed"
        :before-upload="wrappedBeforeUpload"
        :http-request="doUpload"
        :multiple="false"
        v-bind="$attrs"
      >
        <slot name="trigger">
          <el-button type="primary" :disabled="uploading">{{ buttonText }}</el-button>
        </slot>
        <template #tip>
          <div class="el-upload__tip">{{ tipTextComputed }}</div>
        </template>
      </el-upload>
  
      <!-- 只有当 :manual="true" 时才显示提交按钮 -->
      <slot name="submit" v-if="manual">
        <el-button type="success" :loading="uploading" :disabled="uploading" @click="submit">
          {{ submitText }}
        </el-button>
      </slot>
  
      <slot name="template" v-if="templateUrl">
        <el-button link @click="downloadTemplate">{{ templateBtnText }}</el-button>
      </slot>
    </div>
  </template>
  
  <script setup>
  import { ref, computed, getCurrentInstance } from 'vue'
  import { ElMessage } from 'element-plus'
  import request from '@/utils/request'
  import { getToken } from '@/utils/auth'
  
  defineOptions({ name: 'ExcelUploader' })
  
  /* ======== Props（保持父组件调用不变） ======== */
  const props = defineProps({
    action: { type: String, required: true },                 // /sbtz/sbtz/excel
    method: { type: String, default: 'post' },
    data:   { type: Object, default: () => ({}) },            // 额外表单字段
    name:   { type: String, default: 'file' },                // 文件字段名
    headers:{ type: Object, default: () => ({ Authorization: 'Bearer ' + getToken() }) },
  
    accept: { type: String, default: '.xlsx,.xls' },
    size:   { type: Number, default: 500 },                   // MB
    limit:  { type: Number, default: 1 },
    showFileList: { type: Boolean, default: false },
  
    manual: { type: Boolean, default: false },                // =true 时需点击提交
    autoClear: { type: Boolean, default: true },              // 成功后清文件
  
    inline: { type: Boolean, default: true },
    buttonText: { type: String, default: '选择Excel' },
    submitText: { type: String, default: '开始导入' },
    tipText: { type: String, default: '' },
  
    // 兼容父组件的 template-url / template-name 写法（kebab 在模板、camel 在脚本）
    templateUrl: { type: String, default: '' },
    templateName: { type: String, default: '导入模板.xlsx' },
    templateBtnText: { type: String, default: '下载模板' }
  })
  const tipTextComputed = computed(() => props.tipText || `仅支持 .xlsx/.xls，≤ ${props.size}MB`)
  
  /* ======== Emits ======== */
  const emit = defineEmits(['success','error','progress','complete','change'])
  
  /* ======== Refs ======== */
  const uploader = ref(null)
  const uploading = ref(false)
  const { proxy } = getCurrentInstance()
  
  /* ======== Methods ======== */
  function handleExceed(files) {
    const file = files[0]
    uploader.value?.clearFiles()
    uploader.value?.handleStart(file)
  }
  
  async function wrappedBeforeUpload(file) {
    const okExt  = /\.(xlsx|xls)$/i.test(file.name)
    const okSize = file.size / 1024 / 1024 <= props.size
    if (!okExt)  ElMessage.error('请上传 .xlsx 或 .xls 文件')
    if (!okSize) ElMessage.error(`文件需小于等于 ${props.size}MB`)
    if (!okExt || !okSize) return false
    emit('change', file)
    return true
  }
  
  async function doUpload({ file, onProgress, onError, onSuccess }) {
    const fd = new FormData()
    fd.append(props.name, file)
    Object.entries(props.data || {}).forEach(([k, v]) => fd.append(k, v == null ? '' : v))
  
    uploading.value = true
    try {
      const res = await request({
        url: props.action,
        method: props.method,
        data: fd,
        headers: { 'Content-Type': 'multipart/form-data', ...(props.headers || {}) },
        onUploadProgress: (e) => {
          const percent = Math.round((e.loaded * 100) / (e.total || 1))
          onProgress?.({ percent })
          emit('progress', percent, e)
        }
      })
  
      // 若依常见返回：{ code:200, msg:'xx', data:... }
      const ok = res?.code === 200 || res?.status === 200 || res?.success === true
      if (!ok) throw new Error(res?.msg || '导入失败')
  
      onSuccess?.(res)
      emit('success', res)
      ElMessage.success(res?.msg || '导入成功')
      if (props.autoClear) uploader.value?.clearFiles?.()
    } catch (err) {
      onError?.(err)
      emit('error', err)
      ElMessage.error(err?.msg || err?.message || '上传失败')
    } finally {
      uploading.value = false
      emit('complete')
    }
  }
  
  function submit() {
    const files = uploader.value?.uploadFiles || []
    if (!files.length) return ElMessage.warning('请先选择Excel文件')
    uploader.value.submit()
  }
  
 // 在 ExcelUploader.vue 里替换这个方法
async function downloadTemplate() {
  if (!props.templateUrl) return

  // 方案A：若依官方“返回AjaxResult{code,msg(=fileName)}，再去/common/download拉文件”
  try {
    const r = await request({
      url: props.templateUrl,
      method: 'get'
      // 这里不要设置 responseType: 'blob'，让它按 JSON 走，以便识别 AjaxResult
    })
    // 若依 util.importTemplateExcel("xxx") 的返回一般是 { code: 200, msg: 'xxx.xlsx' }
    const fileName =
      r?.fileName || r?.msg || r?.data || r?.message // 兼容不同封装
    if (r?.code === 200 && fileName) {
      // 再去 /common/download 拉取真正文件
      const blob = await request({
        url: '/common/download',
        method: 'get',
        params: { fileName, delete: true },
        responseType: 'blob'
      })
      saveBlob(blob, props.templateName || fileName)
      return
    }
    // 如果没有返回 fileName，就继续走方案B
  } catch (e) {
    // 忽略异常，继续走方案B
  }

  // 方案B：后端直接写文件流（Content-Disposition），我们直接按 blob 保存
  try {
    const blob = await request({
      url: props.templateUrl,
      method: 'get',
      responseType: 'blob'
    })
    // 这时拿不到响应头里的文件名（若依 request 通常只返回 data），
    // 就用 props.templateName 兜底
    saveBlob(blob, props.templateName || '模板.xlsx')
  } catch (e) {
    ElMessage.error('模板下载失败，请联系管理员或检查接口：' + (e?.message || ''))
  }
}

// 小工具：保存 blob
function saveBlob(data, filename = 'download.xlsx') {
  try {
    const url = URL.createObjectURL(new Blob([data]))
    const a = document.createElement('a')
    a.href = url
    a.download = filename
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(url)
  } catch (e) {
    console.error(e)
    ElMessage.error('浏览器不支持文件下载')
  }
}

  
  defineExpose({ submit })
  </script>
  
  <style scoped>
  .excel-uploader :deep(.el-upload){ display:inline-flex; }
  </style>
  